#ifndef FLV2X264CONVERTER_H
#define FLV2X264CONVERTER_H

#include <QObject>
#include <QByteArray>

#define HTON16(x)  ((x>>8&0xff)|(x<<8&0xff00))
#define HTON24(x)  ((x>>16&0xff)|(x<<16&0xff0000)|x&0xff00)
#define HTON32(x)  ((x>>24&0xff)|(x>>8&0xff00)|\
    (x << 8 & 0xff0000) | (x << 24 & 0xff000000))

const char h264space[] = {0x00, 0x00, 0x00, 0x01};

inline bool read8(char *input, int size, int &offset, int &i1){
    i1 = *((char *)(input + offset));
    offset += 1;
    return offset < size;
}

inline bool read16(char *input, int size, int &offset, int &i2){
    i2 = *((short *)(input + offset));
    offset += 2;
    i2 = HTON16(i2);
    return offset < size;
}

inline bool read24(char *input, int size, int &offset, int &i3){
    i3 = (*((int *)(input + offset))) & (0x00ffffff);
    offset += 3;
    i3 = HTON24(i3);
    return offset < size;
}

inline bool read32(char *input, int size, int &offset, int &i4){
    i4 = *((int *)(input + offset));
    offset += 4;
    i4 = HTON32(i4);
    return offset < size;
}

inline bool peek8(char *input, int size, int &offset, int &i1){
    i1 = *((char *)(input + offset));
    return offset < size;
}

inline bool readtime(char *input, int size, int &offset, int &itime)
{
    if (!read32(input, size, offset, itime))
        return false;
    itime = HTON24(itime);
    itime |= (itime & 0xff000000);
    return true;
}

inline void h264_parse(char *input, int size, int & offset, int datelength, QByteArray & output)
{
    int info = 0;
    read8(input, size, offset, info);
    int avctype = 0;
    read8(input, size, offset, avctype);
    offset += 3;
    int templength = 0;
    if (avctype == 0)
    {
        offset += 6;
        read16(input, size, offset, templength);
        fprintf(stderr, "sssize:%d\n", templength);
        output += QByteArray(h264space, sizeof(h264space));
        output += QByteArray(input + offset, templength);
        offset += templength;

        read8(input, size, offset, templength);//ppsnum
        read16(input, size, offset, templength);//ppssize
        fprintf(stderr, "ppsize:%d\n", templength);

        output += QByteArray(h264space, sizeof(h264space));
        output += QByteArray(input + offset, templength);
        offset += templength;
    }
    else
    {
        //可能存在多个nal，需全部读取
        int countsize = 2 + 3;
        while (countsize<datelength)
        {
            read32(input, size, offset, templength);
            output += QByteArray(h264space, sizeof(h264space));
            output += QByteArray(input + offset, templength);
            offset += templength;
            countsize += (templength + 4);
        }
    }
}

inline bool to_h264(char *input, int size, QByteArray &output)
{
    int offset = 0;
    int type = 0;
    int time = 0;
    int datelength = 0;
    int info = 0;
    if (!read8(input, size, offset, type))
        return false;
    if (!read24(input, size, offset, datelength))
        return false;
    if (!readtime(input, size, offset, time))
        return false;
    offset += 3;
    if (!peek8(input, size, offset, info))
        return false;
    if (type == 9)
        h264_parse(input, size, offset, datelength, output);
    offset += datelength;
    return true;
}

#endif // FLV2X264CONVERTER_H
